package com.inspur.neoinput.neo4j.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.inspur.neoinput.neo4j.entity.EntityRel;
import com.inspur.neoinput.neo4j.service.EntityRelService;
import com.inspur.neoinput.neo4j.service.ICodeService;
import com.inspur.neoinput.neo4j.service.NormalizeTermService;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.driver.v1.Session;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.RelationshipType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static org.neo4j.driver.v1.Values.parameters;

@Service
public class CodeServiceImpl implements ICodeService {

    @Autowired
    private NormalizeTermService normalizeTermService;

    @Autowired
    private EntityRelService entityRelService;

    //数据库保存路径
    private static final String DB_PATH = "D:\\java\\java-ruanjian\\neo4j\\Neo4j Desktop\\data\\databases\\graph.db";

    private GraphDatabaseService graphDB;

    private enum RelTypes implements RelationshipType {
        CRIME, LINK, SPRING,
    }

    /**
     * 同步节点操作
     *
     * @param url
     * @param username
     * @param password
     */
    @Override
    public void inputMethod(String url, String username, String password) {
        Driver driver = createDrive(url, username, password);

        //获取节点和标签信息
        List<Map<String, String>> nodeAndLableList = normalizeTermService.getNodeAndLable();

        //存放所有标签
        Set<String> nodeAndLableSet = new HashSet<>();
        for (Map<String, String> nodeAndLablemap : nodeAndLableList) {
            if (nodeAndLablemap.get("entityTypeNameCn") != null) {
                nodeAndLableSet.add(nodeAndLablemap.get("entityTypeNameCn"));
            }
        }

        //存放标签和name属性，格式  key：标签   value：List<name>
        Map<String, List<String>> map = new HashMap<>();
        //存入带标签数据
        for (String nodeAndLableStr : nodeAndLableSet) {
            List<String> list = new ArrayList<>();
            for (Map<String, String> nodeAndLablemap : nodeAndLableList) {
                if (nodeAndLableStr.equals(nodeAndLablemap.get("entityTypeNameCn"))) {
                    list.add(nodeAndLablemap.get("normalizeTermCn"));
                }
            }
            map.put(nodeAndLableStr, list);
        }
        //条件查询
        QueryWrapper<EntityRel> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", "1");
        queryWrapper.isNull("entity_word1_id");
        queryWrapper.select("entity_word1_name");
        //获取entity_rel表节点数据
        List<EntityRel> entityRelList = entityRelService.list(queryWrapper);
        Set<String> set = new HashSet<>();
        for (EntityRel entityRel : entityRelList) {
            set.add(entityRel.getEntityWord1Name());
        }
        List<String> list = new ArrayList<>(set);
        QueryWrapper<EntityRel> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("status", "1");
        queryWrapper2.isNull("entity_word2_id");
        queryWrapper2.select("entity_word2_name");
        List<EntityRel> entityRelList2 = entityRelService.list(queryWrapper2);
        Set<String> set2 = new HashSet<>();
        for (EntityRel entityRel : entityRelList2) {
            set2.add(entityRel.getEntityWord2Name());
        }
        //无标签节点
        List<String> list2 = new ArrayList<>(set2);
        list.addAll(list2);
        //组ID节点
        List<String> list3 = getGroupId();
        list.addAll(list3);
        map.put("NoLable", list);
        //执行cql
        Session session = driver.session();
        for (String keyStr : map.keySet()) {
            List<String> nameList = map.get(keyStr);
            for (String listStr : nameList) {
                session.run("MERGE (a:" + keyStr + " { name: {name} }) RETURN a.name",
                        parameters("name", listStr));
                System.out.println(keyStr);
            }
        }
        session.close();
        driver.close();
    }

    @Override
    public void inputRelation(String url, String username, String password) {
        Driver driver = createDrive(url, username, password);
        Session session = driver.session();
        //获取所有关系
        List<Map<String, String>> typeAndRelList = normalizeTermService.getTypeAndRel();
        for (Map<String, String> typeAndRelMap : typeAndRelList) {
            String entityWord1Name = typeAndRelMap.get("entityWord1Name");//首标签名称
            String entityType1Name = typeAndRelMap.get("entityType1Name");//首标签类型
            String entityWord2Name = typeAndRelMap.get("entityWord2Name");//尾标签类型
            String entityType2Name = typeAndRelMap.get("entityType2Name");//尾标签名称
            String desc = typeAndRelMap.get("desc");//关系名称
            String relGroupId = typeAndRelMap.get("relGroupId");//关系组ID
            if (desc != null) {
                desc = desc.replace("/", "");
            } else {
                desc = "connect";
            }
            //执行创建关系cql
            getCql(entityType1Name, entityWord1Name, session, entityType2Name, entityWord2Name, desc, relGroupId);
        }

        session.close();
        driver.close();
    }

    public void getCql(String entityType1Name, String entityWord1Name, Session session, String entityType2Name, String entityWord2Name, String desc, String relGroupId) {
        if (entityType1Name == null) {
            entityType1Name = "NoLable";
        }
        if (entityType2Name == null) {
            entityType2Name = "NoLable";
        }

        if ("0".equals(relGroupId)) {
//            System.out.println("match (n:"+entityType1Name+"{name:\""+entityWord1Name+"\"}),(m:"+entityType2Name+"{name:\""+entityWord2Name+"\") merge (n)-[r:" + desc + "]->(m)");
            //插入节点操作
            session.run("match (n:" + entityType1Name + "{name:{name1}}),(m:" + entityType2Name + "{name:{name2}}) merge (n)-[r:" + desc + "]->(m)",
                    parameters("name1", entityWord1Name, "name2", entityWord2Name));


        } else {
//            System.out.println("match (n:"+entityType1Name+"{name:\""+entityWord1Name+"\"}),(m:"+entityType2Name+"{name:\""+relGroupId+"\") merge (n)-[r:" + "i" + "]->(m)");
//            System.out.println("match (n:"+entityType1Name+"{name:\""+relGroupId+"\"}),(m:"+entityType2Name+"{name:\""+entityWord2Name+"\") merge (n)-[r:" + desc + "]->(m)");
            //首节点->组ID
            session.run("match (n:" + entityType1Name + "{name:{name1}}),(m:NoLable{name:{name2}}) merge (n)-[r:" + "i" + "]->(m)",
                    parameters("name1", entityWord1Name, "name2", relGroupId));
            //组ID->尾结点
            session.run("match (n:NoLable{name:{name1}}),(m:" + entityType2Name + "{name:{name2}}) merge (n)-[r:" + desc + "]->(m)",
                    parameters("name1", relGroupId, "name2", entityWord2Name));
        }
    }

    public List<String> getGroupId() {
        return normalizeTermService.getGroupId();
    }

    @Override
    public Driver createDrive(String url, String username, String password) {
        return GraphDatabase.driver(url, AuthTokens.basic(username, password));
    }

    @Override
    public void deleteRelation(String url, String username, String password) {
        Driver driver = createDrive(url, username, password);
        //删除关系cql
        Session session = driver.session();
        session.run("MATCH p=()-->() DELETE p",
                parameters());
        session.close();
        driver.close();
    }
}
